package com.wfh.mianshiji.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wfh.mianshiji.common.ErrorCode;
import com.wfh.mianshiji.config.MinioConfig;
import com.wfh.mianshiji.exception.BusinessException;
import com.wfh.mianshiji.model.entity.Resume;
import com.wfh.mianshiji.model.vo.UserVo;
import com.wfh.mianshiji.service.ResumeService;
import com.wfh.mianshiji.mapper.ResumeMapper;
import com.wfh.mianshiji.service.UserService;
import com.wfh.mianshiji.utils.ResumeParseUtil;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;

/**
* @author fenghuanwang
* @description 针对表【resume(简历表)】的数据库操作Service实现
* @createDate 2025-10-30 15:36:18
*/
@Service
@Slf4j
public class ResumeServiceImpl extends ServiceImpl<ResumeMapper, Resume>
    implements ResumeService{

    @Resource
    private UserService userService;

    @Resource
    private MinioClient minioClient;

    @Resource
    private MinioConfig minioConfig;

    @Resource
    private ResumeParseUtil resumeParseUtil;

    /**
     * 上传简历
     *
     * @param resume 简历文件
     * @param request HTTP 请求
     * @return 返回简历 ID（Long 类型）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String upload(MultipartFile resume, HttpServletRequest request) {
        UserVo currentUser = userService.getCurrentUser(request);
        Long userId = currentUser.getId();

        String originalFilename = resume.getOriginalFilename();
        if (originalFilename == null || originalFilename.isEmpty()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件名不能为空");
        }

        String baseName = FilenameUtils.getBaseName(originalFilename);
        String extension = FilenameUtils.getExtension(originalFilename);
        String resumePath = userId + File.separator + baseName + UUID.randomUUID() + "." + extension;
        // 1. 先创建一个“待处理”的简历记录（此时 content 为空）
        Resume placeholderResume = new Resume();
        placeholderResume.setUserId(userId);
        placeholderResume.setName(baseName);
        placeholderResume.setCoverImg("https://ts4.tc.mm.bing.net/th/id/OIP-C.gRfEvaXpnpJ_gdlpz91H4gHaKe?rs=1&pid=ImgDetMain&o=7&rm=3");
        placeholderResume.setContent("");
        // 保存到数据库，获取 ID
        boolean saved = this.save(placeholderResume);
        if (!saved) {
            log.error("无法保存简历占位记录，用户ID: {}", userId);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "简历初始化失败");
        }
        Long resumeId = placeholderResume.getId();
        // 2. 异步处理文件上传和内容解析（使用虚拟线程）
        byte[] fileBytes;
        try {
            fileBytes = resume.getBytes();
        } catch (Exception e) {
            log.error("读取上传文件失败", e);
            // 注意：此时数据库已有记录，但内容为空，可后续重试或标记失败
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "文件读取失败");
        }
        Thread.startVirtualThread(() -> {
            try (InputStream is = new ByteArrayInputStream(fileBytes)) {
                // 上传到 MinIO
                minioClient.putObject(
                        PutObjectArgs.builder()
                                .bucket(minioConfig.getBucket())
                                .stream(is, fileBytes.length, -1)
                                .contentType("application/octet-stream")
                                .object(resumePath)
                                .build()
                );
                log.info("用户:{} 简历文件上传至 MinIO 成功，路径: {}", userId, resumePath);
                // 使用 Apache Tika 提取内容
                String content = resumeParseUtil.parse(resumePath);
                log.info("用户:{} 简历解析成功", userId);
                // 更新数据库中的内容
                Resume updatedResume = new Resume();
                updatedResume.setId(resumeId);
                updatedResume.setContent(content);
                boolean updateSuccess = this.updateById(updatedResume);
                if (!updateSuccess) {
                    log.error("更新简历内容失败，ID: {}", resumeId);
                } else {
                    log.info("简历内容更新成功，ID: {}", resumeId);
                }

            } catch (Exception e) {
                log.error("简历异步处理失败，用户ID: {}, 简历ID: {}", userId, resumeId, e);
                // 可选：更新状态为 failed
                try {
                    Resume failedResume = new Resume();
                    failedResume.setId(resumeId);
                    this.updateById(failedResume);
                } catch (Exception ex) {
                    log.error("更新简历失败状态也失败了", ex);
                }
            }
        });

        return String.valueOf(resumeId);
    }
}




